/**
 * Created by seeker910 on 2017/4/22.
 * @description 内存缓存：对象在缓存中，则在缓存中获取；对象不在缓存中，自动向服务端请求。  
 * @description 有实效性，过期的对象会被从缓存中移除,且5分钟之内只执行一次清理
 * @description 数据不落地，仅存在内存中；不适合处理数据量较大的缓存
 * @description 一次请求的返回作为一条缓存对象，即:load方法执行一次仅会产生一个缓存对象。适合按需冷热数据加载缓存。
 */
Rsd.define('Rsd.data.Cache', {
    extend: 'Rsd.common.Object',
    xtype: 'cache',
    /*
     数据源代理 
     可以是Rsd.common.Service，也可以是用于创建Rsd.common.Service的参数config对象{}
     * */
    proxy:{},
    //缓存对象惟一标识属性名称
    keyName:'',  
    //用于存储数据的容器
    //container:'',
    /**
     * 允许的最大缓存记录数，0:表示不限制
     */
    max:0,
    /**
     * 缓存有效期,默认30分钟，每次使用会，清理掉已过期缓存
     */
    duration:1000*60*30,
    /**
     * 缓存清理时间间隔
     */
    clearInterval:1000*60*5,
    /**
     * 上次清理时间
     */
    lastClearTime:Date.now(),
    /*
     * */
    constructor: function Cache(config) {
        config = config || {};
        this.apply(config);  
    },
    /**
     * @description 用于动态【逐条】加载缓存数据，一次请求的返回作为一条缓存对象
     * @param {*} args 
     * @param {*} callback 
     */
    load:function load(args,callback)
    {
        var me = this;
        var _args = args || {};
        if(Rsd.isEmpty(me.keyName))
        {
            Rsd.error("Rsd.data.Cache对象未设置keyName属性，数据无法被缓存。");
        }
        //缓存
        var _callback = function _cache_callback(resp)
        {
            //debugger;
            if(resp.success && !Rsd.isEmpty(resp.data))
            {
                var data = resp.data||{};
                var list=[];
                var key = data[me.keyName]
                if(Rsd.isEmpty(key))
                {
                    Rsd.error("对象" + me.keyName + "属性值为空，数据无法被缓存。");
                }
                else
                {
                    if(me.container[key]){ 
                        me.container[key].expireAt = Date.now() + me.duration,
                        me.container[key].data = data;
                        list = me.container[key].callbacks||[];
                        me.container[key].callbacks=[];
                    }
                    else
                    {
                        me.container[key] = {
                            expireAt:Date.now() + me.duration,
                            data:data,
                            callbacks:[]
                        };
                    }
                    //处理待回调队列中的回调
                    for(var i in list)
                    {
                        Rsd.callFunction(me,list[i],[data]);
                    }
                    //处理请求结束回调
                    if(callback)
                    {
                        Rsd.callFunction(me,callback,[data]);
                    }
                }
                
            }
           
        }

        me.proxy = me.proxy || {};
        // debugger;
        if(me.proxy instanceof Rsd.data.Service){
            me.proxy.request(_args,_callback);
        }
        else
        {
            me.proxy.url = me.proxy.url || me.url;
            //获取并缓存
            Rsd.httpRequest(me.proxy ,_args,_callback);
        }
    },
    /**
     * 
     * @param {*} key keyName对映字段的值
     * @param {*} callback 缓存数据存在时的回掉处理
     * @returns 缓存数据对象，可通过该返回值，来判断数据是否存在，从而进一步加载数据
     */
    get:function get(key,callback) {

        var me = this;
        
        if(key == undefined || key == null || key == ""  )
        {
            throw new Error("参数key值无效:不允许为空。");
        }
        var data= null;
        //debugger;
        if(this.container.hasOwnProperty(key))
        {
            data = this.container[key].data;
            if(data != null && data != undefined)
            {  
                //延长有效期
                this.container[key].expireAt = Date.now() + me.duration;
                Rsd.callFunction(this,callback,[data]);
            }
            else
            {
                this.container[key].callbacks.push(callback);
            } 
        }
        else
        { 
            this.container[key] = {callbacks:[],data:null};
            //对象不存在时 注册回调方法到待处理队列,在获取到数据时再次回调
            this.container[key].callbacks.push(callback); 
        }

        //根据时间配置 进行缓存清理
        if(me.duration > 0 && (me.lastClearTime + me.clearInterval) < Date.now())
        {
            me.lastClearTime = Date.now();
            //清理过期对象
            setTimeout(function() {
                
                for(var k in this.container)
                {
                    if(this.container[k].duration!=0 && this.container[k].duration<Date.now())
                    {
                        this.container[k].data=null;
                    }
                }
            }, 100);
        }
       
        return data;
    },
    /**
     * 
     * @param {*} key 
     * @returns 
     */
    containes:function containes(key)
    {
        return  this.container.hasOwnProperty(key);
    },
    /**
    * */
    clear:function () {
        this.container={};
    },
    /**
    * */
    remove:function (key) {
        delete  this.container[key];
    }

},function (type) {
    
    //存储容器
    var _containerGetter = function () {

        if (!this.hasOwnProperty('__container')) {
            this.__container = {};
        }
        return this.__container;
    };
    var _containerSetter = function (value) {
        if(Rsd.isObject(value))
        {
            this.__container = this.__container||{};
            Rsd.apply(this.__container,value);
        }
    };
    this.defineProperty(type,"container", _containerGetter, _containerSetter,true);

     
});
